import math
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

mag_ = np.ones(16)
ang_ = np.array([-27.3, -38.4, -53.0, -69.3, -90.0, -112.4, -137.0, -159.6,
                 -180.8, -202.4, -222.7, -242.8, -268.9, -296.4, -325.0, -356.8]) / 180 * math.pi
# ang_ = ang_ - np.max(ang_)

ang_fi = np.array([-96.0, -108.3, -125.7, -144.4,
                    -167.7, -189.7, -209.3, -229.2,
                    -249.7, -268.6, -290.1, -315.0,
                   -342.1, -372.5, -409.0, -439.4, ]) / 180 * math.pi
ang_fi = ang_fi - np.max(ang_fi)

multi_beam_IDEALzz = np.array([[[30, 0, 0], [30, 90, 0], [30, 180, 0], [30, 270, 0]],
                                 [[30, 0, 0], [25, 100, 0], [45, 200, 0], [35, 280, 0]],
                                 [[30, 0, -3], [30, 90, -10], [30, 180, -5], [30, 270, 0]],
                                 [[30, 0, -3], [25, 100, -10], [45, 200, -5], [35, 280, 0]]])
def UV_Sector(TT):
    beamwidth_uv = 0.096
    beamwidth_1db_uv = 0.021

    phi_sector = 60 * math.pi / 180
    theta_inc = 25 * math.pi / 180
    ki = math.asin(beamwidth_uv)-math.asin(beamwidth_1db_uv)
    LowC = 1000
    UpC = 30

    MASK_U = np.ones((TT, TT))
    MASK_L = np.zeros((TT, TT))
    for i in range(TT):
        for j in range(TT):
            u = i / (TT - 1) * 2 - 1
            v = j / (TT - 1) * 2 - 1
            if u ** 2 + v ** 2 < 1:
                MASK_U[i, j] = 10 ** (-UpC / 10)
                phii = math.atan2(v, u)
                sinthetaa = np.sqrt(u*u+v*v)
                if abs(sinthetaa-math.sin(theta_inc)) < beamwidth_uv and abs(phii) < phi_sector/2:
                    MASK_U[i, j] = 1
                if abs(sinthetaa-math.sin(theta_inc)) < beamwidth_1db_uv and abs(phii) < phi_sector/2-ki/math.sin(theta_inc):
                    MASK_L[i, j] = 10 ** ((- 1) / 10)

    return MASK_U, MASK_L

mask_n = 0
def UV_Multibeam(casei, TT):
    if casei==4:
        aa, bb =UV_Sector(TT)
        return aa, bb

    multi_beam_IDEAL = multi_beam_IDEALzz[casei]
    multi_beam_IDEAL_uv = np.zeros((4, 3))
    for i in range(len(multi_beam_IDEAL)):
        multi_beam_IDEAL_uv[i, 0] = math.sin(multi_beam_IDEAL[i, 0] / 180 * math.pi) * \
                                    math.cos(multi_beam_IDEAL[i, 1] / 180 * math.pi)
        multi_beam_IDEAL_uv[i, 1] = math.sin(multi_beam_IDEAL[i, 0] / 180 * math.pi) * \
                                    math.sin(multi_beam_IDEAL[i, 1] / 180 * math.pi)
        multi_beam_IDEAL_uv[i, 2] = multi_beam_IDEAL[i, 2]

    # print("uv position", multi_beam_IDEAL_uv.round(3))

    beamwidth_uv = 0.096
    beamwidth_3db_uv = 0.035

    LowC = 1000
    UpC = 30
    global mask_n
    mask_n = 0
    MASK_U = np.ones((TT, TT))
    MASK_L = np.zeros((TT, TT))
    for i in range(TT):
        for j in range(TT):
            u = i / (TT - 1) * 2 - 1
            v = j / (TT - 1) * 2 - 1
            if u**2 + v**2 < 1:
                mask_n = mask_n+1
                MASK_U[i, j] = 10**(-UpC/10)
                for k in range(len(multi_beam_IDEAL)):
                    if np.sqrt((u - multi_beam_IDEAL_uv[k, 0])**2 + (v-multi_beam_IDEAL_uv[k, 1])**2) < beamwidth_uv:
                        MASK_U[i, j] = 10**(multi_beam_IDEAL[k, 2] / 10)

                    if np.sqrt((u - multi_beam_IDEAL_uv[k, 0])**2 + (v-multi_beam_IDEAL_uv[k, 1])**2) < beamwidth_3db_uv:
                        MASK_L[i, j] = 10**((multi_beam_IDEAL[k, 2] - 3) / 10)

    return MASK_U, MASK_L

def plot_MASK(MASK_L, MASK_U, TT):
    x = np.linspace(-1, 1, TT)
    y = np.linspace(-1, 1, TT)
    X, Y = np.meshgrid(x, y)
    # MASK_L_db = np.log10(MASK_L) * 10
    # MASK_U_db = np.log10(MASK_U) * 10

    plt.subplot(1, 2, 1)
    lvls = np.linspace(0, 1, 21)
    cset = plt.contourf(Y, X, MASK_U, lvls, cmap=mpl.cm.jet, )
    # contour = plt.contour(X, Y, MASK_U_db, 10, colors='k')
    # plt.clabel(contour, fontsize=10, colors='k')
    plt.axis('equal')
    plt.colorbar(cset)

    plt.subplot(1, 2, 2)
    cset = plt.contourf(Y, X, MASK_L, lvls, cmap=mpl.cm.jet, )
    # contour = plt.contour(X, Y, MASK_L_db, 10, colors='k')
    # plt.clabel(contour, fontsize=10, colors='k')
    plt.axis('equal')
    plt.colorbar(cset)
    plt.show()


import numpy as np
def plot_polar_angles(angles_deg, labels=None, color='royalblue', size=120,
                      title='Polar Plot of Angles', zero_location='N'):
    """
    在极坐标圆盘上绘制角度数组

    参数:
        angles_deg (list): 角度值数组(度)，范围[-360, 0]
        labels (list): 各点的标签(可选)
        color (str): 点的颜色(默认为royalblue)
        size (int): 点的大小(默认为120)
        title (str): 图表标题(默认为'Polar Plot of Angles')
        zero_location (str): 0度位置(N, S, E, W，默认为'N'-顶部)
    """
    # 转换为numpy数组并确保是负角度
    angles_deg = np.array(angles_deg)
    assert (angles_deg <= 0).all(), "角度应为负值"

    # 固定半径为1(边缘)
    radii = np.ones_like(angles_deg)

    # 如果没有提供标签，使用数字编号
    if labels is None:
        labels = [str(i + 1) for i in range(len(angles_deg))]
    elif len(labels) != len(angles_deg):
        raise ValueError("标签数量与角度数量不匹配")

    # 创建极坐标图
    fig = plt.figure(figsize=(10, 10))
    ax = fig.add_subplot(111, projection='polar')

    # 关键修正1：正确处理负角度
    plotted_angles = np.where(angles_deg < -360, angles_deg % 360, angles_deg)

    # 绘制点
    ax.scatter(np.deg2rad(plotted_angles), radii, color=color, s=size, alpha=0.7, edgecolor='white')

    # 关键修正2：精确计算标签位置
    label_radius = 1.1  # 标签半径偏移量

    for angle, label in zip(plotted_angles, labels):
        # 转换为弧度
        rad = np.deg2rad(angle)
        # 计算标签坐标
        x = label_radius * np.cos(rad)
        y = label_radius * np.sin(rad)

        # 根据位置调整对齐方式
        ha = 'center'
        va = 'center'
        if -45 <= angle <= 45 or angle <= -315:
            va = 'bottom'
        elif 45 < angle < 135 or -315 < angle < -225:
            ha = 'left'
        elif 135 <= angle <= 225 or -225 <= angle <= -135:
            va = 'top'
        else:
            ha = 'right'

        ax.text(rad, label_radius, label,
                ha=ha, va=va, fontsize=20, color='r',)
#                bbox=dict(facecolor='white', alpha=0.8, boxstyle='round', edgecolor='none'))

    # 关键修正3：优化极坐标设置
    ax.set_theta_zero_location(zero_location)
    ax.set_theta_direction(-1)  # 顺时针方向

    # 设置16等分的角度网格（0°到360°）
    ax.set_xticks(np.linspace(0, 2 * np.pi, 16, endpoint=False))
    ax.set_xticklabels([f'{round(i, 2)}°' for i in np.linspace(0, 360, 16, endpoint=False)], size=16)

    # 设置圆形范围和网格
    ax.set_rlim(0, 1.5)
    ax.set_rticks([1.0])
    ax.grid(True, linestyle='--', alpha=0.5)

    # 美化标题
    # ax.set_title(title, pad=25, fontsize=14, fontweight='bold')

    plt.tight_layout()
    plt.show()


if __name__ == '__main__':
    # Gred_code4 = ['0000', '0001', '0011', '0010', '0110', '0111', '0101', '0100',
    # '1100', '1101', '1111', '1110', '1010', '1011', '1001', '1000']
    # plot_polar_angles(ang_/math.pi*180, labels=Gred_code4, size=200, color='r')

    Mm = 120
    MASK_U1, MASK_L1 = UV_Multibeam(0, Mm)
    plot_MASK(MASK_U1, MASK_L1, Mm)